/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package analisador;

import java.io.File;
import java.io.PrintWriter;
import java.sql.*;
import java.util.*;
import util.Arquivos;

/**
 *
 * @author andre
 */
public class MiniMundoWeka2 {
static Map<String, Integer> mapTokens;
    static List<String> listaOrdenada;
    static Map<String, Collection<String>> listaAdjacenciaAutor = new HashMap<String, Collection<String>>();
    static Map<String, Set<Integer>> mapMensagensAutor = new HashMap<String, Set<Integer>>();
    static Map<String, List<Boolean>> mapIssue = new HashMap<String, List<Boolean>>();
    static Map<String, Set<String>> mapIssueAutor = new HashMap<String, Set<String>>();
    static ArrayList<Boolean> lista;
    static Connection con;
    static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    static int branco = 0;
    
    static String dataMax, dataMin;

    public static void main(String[] args) throws Exception {

        String autor = "eli";
      
        
        MiniMundoWeka2.gerar(autor); 
    }

    public static void conectar() throws Exception {
        con = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/hdfs",
                "root",
                "root");
    }

    public static void desconectar() throws Exception {
        con.close();
    }
    
    public static void getDataMaxMin(String autor) throws Exception{

        String query = "SELECT max(datacomentario) as maximo, min(datacomentario) as minimo FROM comentario WHERE autor=?";
        PreparedStatement ps = con.prepareStatement(query);
        ps.setString(1, autor);
        ResultSet rs = ps.executeQuery();
        if(rs.next()){
            dataMax = rs.getString("maximo");
            dataMin = rs.getString("minimo");
        }
        rs.close();
        ps.close();
    }

    public static void gerar(String autor) throws Exception {
        conectar();
        System.out.printf("Consulta na base...");
        getDataMaxMin(autor);

        String query = "SELECT id, tokensordered, autor, issue_id FROM comentario WHERE datacomentario>=? AND datacomentario <=?";
        PreparedStatement ps = con.prepareStatement(query);
        ps.setString(1, dataMin);
        ps.setString(2, dataMax);
        System.out.println(ps.toString());
        ResultSet rs = ps.executeQuery();
      
        
        geraMiniMundo(rs, autor);
//        geraMensagens(rs, nome);
//        agrupaMensagensIssue();

        rs.close();
        desconectar();
    }

    private static void geraMiniMundo(ResultSet rs, String nome) throws SQLException {
        System.out.println("\nGerando MiniMundo...");
        long cont = 0;
        mapTokens = new HashMap<String, Integer>();
        while (rs.next()) {
            long id = rs.getLong("id");
            String tokens = rs.getString("tokensordered");
            insertMiniMundo(id, tokens);
            if (++cont % 1000 == 0) {
                System.out.println(cont);
                System.gc();
            }
        }
        System.out.println(branco);
        //lista ordenada dos tokens
        listaOrdenada = new ArrayList<String>(mapTokens.keySet());
        Collections.sort(listaOrdenada);
        lista = new ArrayList<Boolean>(listaOrdenada.size() + 1);

        StringBuilder b = new StringBuilder();
        for (String s : listaOrdenada) {
            lista.add(false);
            b.append(s);
            b.append("\n");
        }
        String nomeArquivo = String.format("arquivosGerados/%sMiniMundo.txt", nome);
        Arquivos.gravar(nomeArquivo, b.toString(), false);
    }

    private static void insertMiniMundo(long id, String tokens) {
        try {
            StringTokenizer tokenizer = new StringTokenizer(tokens);
            while (tokenizer.hasMoreTokens()) {
                String token = tokenizer.nextToken();
                Integer frequency = mapTokens.get(token);
                if (frequency == null) {
                    mapTokens.put(token, 1);
                } else {
                    mapTokens.put(token, frequency + 1);
                }
            }
        } catch (NullPointerException ex) {
            branco++;
        }
        
    }

    public static void geraMensagens(ResultSet rs, String nome) throws Exception {
        String nomeArquivo = String.format("arquivosGerados/%sMiniMundo.Mensagens.txt", nome);
        File arquivo = new File(nomeArquivo);
        PrintWriter printWriter = new PrintWriter(arquivo);

        long tInicial, tFinal;
        System.out.println("\nGerando Mensagens...");
        rs.first();
        long cont = 0;
        tInicial = System.currentTimeMillis();
        do {
            long id = rs.getLong("id");
            String autor = rs.getString("autor");
            String issue = rs.getString("issue_id");
            String tokens = rs.getString("tokens");
            geraVetorMensagem(id, autor, issue, tokens, printWriter);
            if (++cont % 1000 == 0) {
                tFinal = System.currentTimeMillis();
                System.out.printf("%d: %dms %n", cont, (tFinal - tInicial));
                tInicial = tFinal;
                System.gc();
            }
        } while (rs.next());
        printWriter.flush();
        printWriter.close();
    }

    private static void geraVetorMensagem(long id, String autor, String issue, String tokens, PrintWriter printWriter) throws Exception {
        if (tokens != null) {
            StringTokenizer tokenizer = new StringTokenizer(tokens);
            if (!mapIssue.containsKey(issue)) {
                //listaAdjacenciaAutor.put(autor, new HashSet<String>());
                mapIssue.put(issue, (ArrayList<Boolean>) lista.clone());
                mapIssueAutor.put(issue, new HashSet<String>());

            }
            mapIssueAutor.get(issue).add(autor);
            int posicao = -1;
            while (tokenizer.hasMoreTokens()) {
                String token = tokenizer.nextToken();
                posicao = Collections.binarySearch(listaOrdenada, token);
                mapIssue.get(issue).set(posicao, true);
            }
        }
    }

    public static void agrupaMensagensIssue() throws Exception {
        StringBuilder head = new StringBuilder();
        head.append("@relation eli\n\n");
        for (int i=0; i< listaOrdenada.size(); i++) {
            head.append("@attribute ");
            head.append(i);
            head.append(" {0,1}\n");
        }
        head.append("@attribute resultado {0, 1}\n");
        head.append("\n");
        head.append("@data\n");

        Arquivos.gravar(String.format("arquivosGerados/MiniMundo.Issues.arff"), head.toString(), true);

        for (Map.Entry<String, List<Boolean>> e : mapIssue.entrySet()) {
            String issue = e.getKey();
            StringBuilder ocorrencias = new StringBuilder();
            for (Boolean s : e.getValue()) {
                ocorrencias.append((s.booleanValue() ? 1 : 0));
                ocorrencias.append(", ");
            }
            boolean flag = mapIssueAutor.get(issue).contains("eli");
            ocorrencias.append(flag? 1:0);
            String nomeArquivo = String.format("arquivosGerados/MiniMundo.Issues.arff", issue);
            Arquivos.gravar(nomeArquivo, ocorrencias.toString(), true);
        }
    }
}
